#pragma once

#include <stdio.h>
#include <iostream>
#include <string>
#include <vector>
#include <cstdio>
#include <ctime>
#include "FrontEndController.h"
#include "QueryExpressionParser.h"


using namespace std;

/*
Contructors
*/
FrontEndController::FrontEndController(void) {
	//cout << "Front-End Controller initialized.\n";
	
	pkb = new PKB();
	parser = new Parser(pkb);
	de = new DesignExtractor(pkb);
	QueryExpressionParser *expressionParser = new QueryExpressionParser(pkb);
	queryProcessor = new QueryProcessorWrapper(new QueryPreprocessor(expressionParser), new QueryEvaluator(pkb), new QueryProjector());
}

FrontEndController::~FrontEndController(void) {
}


/*
Wrapper for entire front end  
*/
void FrontEndController::frontEndInit() {
	// initialise all the stuff here
}

void FrontEndController::frontEndParseManual(string source) {
	parser->executeSrc(source);
}

void FrontEndController::frontEndParse(string filename) {
	// call parser here
	//cout << "Front-End Controller calling parser to parse source..\n";

	std::clock_t start;
	double duration;

	start = std::clock();

	ifstream file(filename);
	string sourceCode((std::istreambuf_iterator<char>(file)), (std::istreambuf_iterator<char>()));
	//cout << "Source read in:\n" << sourceCode << "\n";
	//cout << "Starting to parse source code..\n";
	parser->executeSrc(sourceCode);

	de->run();
	de->runExtra();
	
	/* Yu De's debugging */
	/*pkb->printAllWallLines();
	pkb->printAllWallProcs();
	pkb->printAllProcExitToIndexes();
	pkb->printAllHasDirectRouteInProc();
	pkb->printAllIsReachable(true, true);
	pkb->printAllHasLoopBackRoute();
	pkb->printAllHasOutRoute();*/

	duration = ( std::clock() - start ) / (double) CLOCKS_PER_SEC;
	//cout << "FrontEndController::frontEndParse() took " << duration << " seconds\n";
	
}

vector<string> FrontEndController::frontEndEvaluate(string query) {
	// call query evaluator here
	//cout << "Front-End controller calling queryEvaluator..\n";

	std::clock_t start;
	double duration;

	start = std::clock();

	vector<string> results = queryProcessor->evaluateQuery(query);
	//cout << "Results successfully retrieved from queryEvaluator..\n";

	duration = ( std::clock() - start ) / (double) CLOCKS_PER_SEC;
	//cout << "FrontEndController:frontEndEvaluate took " << duration << " seconds\n";

	return results;
}